import constants from '@/constants';
import { HuifuService } from '@/core/huifu.service';
import { CurrentUser, Public, RealIp } from '@/decorators';
import { WalletOrderStatusEnum } from '@/enums';
import { halt, ok } from '@/utils';
import { InjectQueue } from '@nestjs/bull';
import { Body, Controller, Get, Post } from '@nestjs/common';
import { SkipThrottle, Throttle, seconds } from '@nestjs/throttler';
import { Queue } from 'bull';
import dayjs from 'dayjs';
import Decimal from 'decimal.js';
import getMAC from 'getmac';
import { BaseController } from './base.controller';

@Controller('huifu')
export class HuifuController extends BaseController {
  constructor(
    @InjectQueue('wallet')
    private readonly walletQueue: Queue,
    private readonly huifuService: HuifuService,
  ) {
    super();
  }

  @Public()
  @Post('account/callback')
  @SkipThrottle()
  async accountCallback(@Body() dto: any) {
    console.log('汇付钱包开户回调通知:', dto);
    const res = await this.huifuService.verifySign(dto.check_value);
    if (res?.resp_code === 'C00000') {
      await this.walletQueue.add('account', {
        no: res?.order_id,
      });
    }
    return 'SUCCESS';
  }

  @Public()
  @Post('wallet/callback')
  @SkipThrottle()
  async walletCallback(@Body() dto: any) {
    console.log('汇付钱包注册回调通知:', dto);
    const res = await this.huifuService.verifySign(dto.check_value);
    console.log(res);
    if (res?.resp_code === 'C00000') {
      await this.walletQueue.add('wallet', {
        no: res?.order_id,
        date: res?.order_date,
        userId: res?.user_id,
      });
    }
    return 'SUCCESS';
  }

  @Post('wallet')
  @Throttle({
    short: {
      ttl: seconds(1),
      limit: 1,
    },
  })
  async wallet(@CurrentUser('id') userId: number, @RealIp() ip: string) {
    const user = await this.prisma.user.findUnique({ where: { id: userId } });
    if (!user) {
      return halt('用户信息异常');
    }
    if (!user.isReal) {
      return halt('请先完成实名认证');
    }
    const date = dayjs();
    const no = await this.huifuService.generateOrderNo();
    const pendingOrder = await this.prisma.walletOrder.findFirst({
      where: {
        ownerId: user.id,
        status: WalletOrderStatusEnum.PENDING,
        isDeleted: false,
      },
    });
    if (!!pendingOrder) {
      return ok({ url: pendingOrder.payUrl });
    }
    const count = await this.prisma.walletOrder.count({
      where: {
        ownerId: user.id,
        status: WalletOrderStatusEnum.COMPLETED,
        isDeleted: false,
      },
    });
    if (count <= 0) {
      const expireAt = dayjs().add(10, 'minutes');
      const total = Number(this.config.get('huifu.openAccountFee'));
      const res = await this.huifuService.pay033({
        order_date: date.format('YYYYMMDD'),
        order_id: no,
        order_expire_time: expireAt.format('YYYYMMDDHHmmss'),
        user_name: user.realname,
        id_card_type: '10',
        id_card: user.idCard,
        trans_amt: new Decimal(total).toFixed(2),
        goods_desc: '开户手续费',
        div_type: '1',
        dev_info_json: JSON.stringify({
          devType: '2',
          ipAddr: ip,
          MAC: getMAC().replaceAll(':', ''),
        }),
        object_info: JSON.stringify({
          marketType: 1,
        }),
        bg_ret_url: `${this.huifuService.NotifyUrl}/api/huifu/account/callback`,
      });
      if (res?.resp_code !== 'C00000') {
        return halt(res.resp_desc);
      }
      const order = await this.prisma.walletOrder.create({
        data: {
          no,
          total,
          expireAt: expireAt.toDate(),
          status: WalletOrderStatusEnum.PENDING,
          ownerId: user.id,
          payUrl: res.pay_url,
          payType: this.config.get('payment'),
        },
      });
      await this.walletQueue.add(
        'account',
        {
          no: order.no,
        },
        {
          delay: expireAt.diff(dayjs()),
        },
      );
      return ok({ url: order.payUrl });
    }
    if (!user.userCustId || !user.acctId) {
      const res = await this.huifuService.openAccount({
        order_date: date.format('YYYYMMDD'),
        order_id: no,
        user_name: user.realname,
        id_card: user.idCard,
        user_id: user.code,
        user_mobile: user.mobile,
        mer_priv: user.id,
      });
      if (res.resp_code === 'A40203') {
        await this.prisma.user.update({
          where: {
            id: user.id,
          },
          data: {
            userCustId: res.user_cust_id,
            acctId: res.acct_id,
          },
        });
      } else {
        if (res?.resp_code !== 'C00000') {
          return halt(res.resp_desc);
        }
        return ok({
          url: res.redirect_url,
        });
      }
    }
    const res = await this.huifuService.accessAccount({
      user_id: user.code,
      order_date: date.format('YYYYMMDD'),
      order_id: no,
    });
    if (res?.resp_code !== 'C00000') {
      return halt(res.resp_desc);
    }
    return ok({
      url: res.redirect_url,
    });
  }

  @Public()
  @Get('test')
  async test(@RealIp() ip: string) {
    return ok();
  }
}
